package com.gonsin.ta.logic.parse.condition;

import com.gonsin.ta.logic.enums.ConditionTypeEnum;
import com.gonsin.ta.logic.exceptions.TaException;
import com.gonsin.ta.logic.node.Node;
import com.gonsin.ta.logic.parse.condition.context.ChainContextImpl;
import com.gonsin.ta.logic.parse.serialize.SerializeContext;
import com.gonsin.ta.logic.parse.serialize.SwitchConditionSerial;
import com.gonsin.ta.logic.parse.serialize.TaDeserializable;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 路由切换
 */
public class SwitchCondition extends Condition {

    private Map<String, List<Executable>> switchMap;

    private Node switchNodeInstance;

    @ApiModelProperty("选择节点名字")
    private String switchNode;

    @ApiModelProperty("方法类型")
    private ConditionTypeEnum conditionType;

    public SwitchCondition(Node switchNodeInstance){
        this.switchMap = new ConcurrentHashMap<>();
        this.switchNodeInstance = switchNodeInstance;
        this.switchNode = switchNodeInstance.getNodeId();
        this.conditionType = ConditionTypeEnum.SWITCH;
    }

    @Override
    public void execute(ChainContextImpl context) throws Exception {
        // 执行switchChain执行的组件，获得返回值
        switchNodeInstance.execute(context);
        String result = context.getSwitchResult();


        // 根据返回值获得下一个要调用的condition，并执行
        List<Executable> executable = switchMap.get(result);
        if(executable == null || executable.size() == 0){
            throw new TaException("在chainId = 【{}】中，未从结果【{}】中找到可执行的节点", context.getChainId(), result);
        }

        for(Executable exe : executable){
            exe.execute(context);
        }
    }

    @Override
    public TaDeserializable toSerializable(SerializeContext serializeContext) {
        SwitchConditionSerial switchConditionSerial = new SwitchConditionSerial();
        switchConditionSerial.setConditionId(getConditionId());
        Map<String, List<TaDeserializable>> serialMap = new HashMap<>();
        switchConditionSerial.setSwitchNode(switchNode);

        switchMap.forEach((k, v) -> {
            List<TaDeserializable> executableList = new ArrayList<>();
            for(Executable exe : v){
                executableList.add(exe.toSerializable(serializeContext));
            }
            serialMap.put(k, executableList);
        });
        switchConditionSerial.setSwitchMap(serialMap);
        return switchConditionSerial;
    }

    public void putCase(String c, List<Executable> cases) {
        switchMap.put(c, cases);
    }

    @Override
    public List<FutureCondition> searchFutureConditions() {
        List<FutureCondition> conditions = new ArrayList<>();
        List<Executable> childs = new ArrayList<>();
        switchMap.values().forEach(childs::addAll);

        for(Executable executable : childs){
            if(executable instanceof FutureCondition){
                conditions.add((FutureCondition) executable);
                continue;
            }
            if(executable instanceof Condition){
                List<FutureCondition> childConditions = ((Condition)executable).searchFutureConditions();
                if(!CollectionUtils.isEmpty(childConditions)){
                    conditions.addAll(childConditions);
                }
            }
        }
        return conditions;
    }

    public void setSwitchNode(String switchNode) {
        this.switchNode = switchNode;
    }

    public void setConditionType(ConditionTypeEnum conditionType) {
        this.conditionType = conditionType;
    }

    public String getSwitchNode() {
        return switchNode;
    }

    public ConditionTypeEnum getConditionType() {
        return conditionType;
    }
    public Map<String, List<Executable>> getSwitchMap() {
        return switchMap;
    }
}
